package fr.lip6.meta.ple.generation.fh.java;

import java.util.ArrayList;

import org.eclipse.emf.common.util.EList;
//import org.eclipse.gmt.modisco.java.ClassInstanceCreation;
import org.eclipse.gmt.modisco.java.ConstructorDeclaration;
import org.eclipse.gmt.modisco.java.Expression;
import org.eclipse.gmt.modisco.java.ExpressionStatement;
import org.eclipse.gmt.modisco.java.ForStatement;
import org.eclipse.gmt.modisco.java.IfStatement;
import org.eclipse.gmt.modisco.java.InfixExpression;
import org.eclipse.gmt.modisco.java.MethodDeclaration;
import org.eclipse.gmt.modisco.java.MethodInvocation;
import org.eclipse.gmt.modisco.java.ReturnStatement;
import org.eclipse.gmt.modisco.java.Statement;
import org.eclipse.gmt.modisco.java.WhileStatement;
import org.eclipse.gmt.modisco.java.emf.impl.AssignmentImpl;
import org.eclipse.gmt.modisco.java.emf.impl.BlockImpl;
import org.eclipse.gmt.modisco.java.emf.impl.ExpressionStatementImpl;
import org.eclipse.gmt.modisco.java.emf.impl.FieldAccessImpl;
import org.eclipse.gmt.modisco.java.emf.impl.ForStatementImpl;
import org.eclipse.gmt.modisco.java.emf.impl.IfStatementImpl;
import org.eclipse.gmt.modisco.java.emf.impl.InfixExpressionImpl;
import org.eclipse.gmt.modisco.java.emf.impl.MethodInvocationImpl;
//import org.eclipse.gmt.modisco.java.emf.impl.NumberLiteralImpl;
import org.eclipse.gmt.modisco.java.emf.impl.ReturnStatementImpl;
import org.eclipse.gmt.modisco.java.emf.impl.SingleVariableAccessImpl;
//import org.eclipse.gmt.modisco.java.emf.impl.StringLiteralImpl;
//import org.eclipse.gmt.modisco.java.emf.impl.TypeAccessImpl;
import org.eclipse.gmt.modisco.java.emf.impl.WhileStatementImpl;

import fr.lip6.meta.ple.generation.strategy.ProcessConstraintStrategy;

import artefact.umlClassDiagram.CreateOperation;

public class ProcessConstraintFHJava implements ProcessConstraintStrategy {
	static ArrayList<String> allvariable=new ArrayList<String>();

	@Override
	public ArrayList<String> getOperationVariables(CreateOperation o) {
		allvariable.clear();
		
		String [] lien = o.getLien().split("::");
		org.eclipse.gmt.modisco.java.Block b = null;
		String params = lien.length > 2 ? lien[2] : null;
		String[] paramsArray = params == null ? new String[0] : params.substring(1, params.length()-1).split(",");
		if (paramsArray.length == 1 && paramsArray[0].equals("")) paramsArray = new String[0];

		if (!o.getName().equals(o.getOwener())) {
			MethodDeclaration md = GenerateFromXmiFHJava.getMethodDeclaration(lien[0], lien[1], o.getOwener(), o.getName(), paramsArray);

			b = md.getBody();
		} else {
			ConstructorDeclaration con = GenerateFromXmiFHJava.getConstructorDeclaration(lien[0], lien[1], o.getOwener(), o.getName(), paramsArray);
			
			b = con.getBody();
		}
		{
			EList<Statement>	sts=b.getStatements();


			for(Statement st:sts)
			{

				getStatementVariables(st);

			}
		}

		return allvariable;
	}

	@Override
	public void getStatementVariables(Statement st)
	{  

		if(st instanceof ExpressionStatement)
		{
			ExpressionStatementImpl es=(ExpressionStatementImpl) st;
			readExpressionStatement(es);
		}

		if(st instanceof ReturnStatement)
		{
			ReturnStatementImpl es=(ReturnStatementImpl) st;
			getReturnStatementBody((ReturnStatement) es);

		}
		if(st instanceof IfStatement)
		{

			IfStatementImpl ifs=(IfStatementImpl) st;
			readIfStatement(ifs);

		}
		if(st instanceof ForStatement)
		{
			ForStatementImpl f=(ForStatementImpl) st;
			getForStatmentBody(f);

		}
		if(st instanceof WhileStatement)
		{
			WhileStatementImpl w=(WhileStatementImpl) st;

			getWhileStatmentBody(w);




		}




	}

	//read exprtionstatemant 
	static void readExpressionStatement(ExpressionStatement es)
	{

		Expression ii =es.getExpression();
		readExpression(ii);

	}

	//end read exprtion statement  

	//read returnstatemant 
	static void getReturnStatementBody(ReturnStatement es)
	{org.eclipse.gmt.modisco.java.
		Expression ex= es.getExpression();
	readExpression(ex);


	}
	//read return statement

	void getForStatmentBody(ForStatement f)
	{

		for(Expression ex: f.getInitializers())
		{
			readExpression(ex);	
		}
		readExpression(f.getExpression());	


		for(Expression ex: f.getUpdaters())
		{
			readExpression(ex);	
		}


		BlockImpl rst=(BlockImpl) f.getBody();
		for(Statement st: rst.getStatements())
		{
			getStatementVariables(st);	
		}





	}

	void  getWhileStatmentBody(WhileStatementImpl w)
	{
		BlockImpl rst=(BlockImpl) w.getBody();
		for(Statement st: rst.getStatements())
		{
			getStatementVariables(st);	
		}




	}

	void readBlock(BlockImpl b)
	{

		for(Statement st: b.getStatements())
		{
			getStatementVariables(st);	
		}


	}


	void  readIfStatement(IfStatement es)
	{
		readExpression(es.getExpression());

		if(es.getThenStatement() instanceof BlockImpl)
		{
			BlockImpl st1=(BlockImpl) es.getThenStatement();
			readBlock(st1);
		}
		else
		{
			getStatementVariables(es.getThenStatement());	
		}
		//
		if(es.getElseStatement()  instanceof BlockImpl)
		{

			BlockImpl st= (BlockImpl) es.getElseStatement();
			readBlock(st);	

		}
		else if(es.getElseStatement()==null)
		{}
		else
		{
			getStatementVariables(es.getElseStatement());


		}

	}


	static void  readExpression(Expression ex)
	{

		if(ex instanceof InfixExpression)
		{

			InfixExpressionImpl res1=(InfixExpressionImpl) ex;

			readExpression(res1.getLeftOperand());
			readExpression(res1.getRightOperand());


		}



		if(ex instanceof AssignmentImpl){
			AssignmentImpl res1=(AssignmentImpl) ex;

			readExpression(res1.getLeftHandSide());
			readExpression(res1.getRightHandSide());


		}



		if(ex instanceof FieldAccessImpl)
		{

			FieldAccessImpl leftside=(FieldAccessImpl) ex;
			allvariable.add( leftside.getField().getVariable().getName());
		}


		if(ex instanceof SingleVariableAccessImpl )
		{		SingleVariableAccessImpl leftside=(SingleVariableAccessImpl) ex;
		if(!allvariable.contains(leftside.getVariable().getName()))
			allvariable.add(leftside.getVariable().getName());
		readExpression(leftside.getQualifier());



		}

		if(ex instanceof MethodInvocation)
		{
			MethodInvocationImpl mo=(MethodInvocationImpl) ex;

			// readExpression(mo.getExpression());


			EList<Expression>  exs=mo.getArguments();
			//int i=0;
			for(Expression ex1 : exs)
			{

				readExpression(ex1);


			}

		}







	}
}
